/******************************************************************************
 cnome: A C++ source "genes" discover. :-)

 See more details at:

   http://www.codeplex.com/cnome

 The original author site is at: http://www.alexandre-barbosa.com/

 Copyright (c) 2008 Alexandre Barbosa.
 Distributed under the MIT License. (See accompanying file LICENSE-MIT.txt 
 or at http://www.codeplex.com/cnome/license)
 ******************************************************************************/

#if defined(_MSC_VER) && (_MSC_VER >= 1400)
#pragma warning ( disable : 4800 )
#pragma warning ( disable : 4996 )
#pragma warning ( disable : 4267 )
#pragma warning ( disable : 4355 )
#endif

#include <fstream>
#include <iostream>
#include <stdio.h>

#include "auxiliar.h"
#include "cnome_iterator.h"
#include "cnome_typedefs.h"
#include "symbol_item.h"

using namespace std;
using namespace boost::wave;

namespace cnome {
const char* cfgFile="cnome.cfg";

const char* my_itoa(int a, char* buf=0) {  // It is not thread safe
	
	static char buffer[20];
	if (!buf)
		buf = buffer;

	sprintf(buf,"%d",a);
	//return itoa(a,buffer,10);
	return buf;
}

std::string adns2Str(const adornersT& adns) {
	std::string ret;
	for (adornersT::const_iterator it = adns.begin(); it!=adns.end(); it++)
		ret += *it==T_CONST?string(" ")+it->get_value().c_str():it->get_value().c_str();

	return ret;
}

void PrintSymbols() {
	char strLinNum[20];
	char strColNum[20];
	
	for (itSymbolItem it = cnome_symbols.begin(); it != cnome_symbols.end(); it++) {
			if ( it->second->get_symbol_type() != symbolItem::internal &&
				 (	    it->second->get_symbol_type() != symbolItem::keyword 
				    ||  it->second->get_symbol_status() != symbolItem::declared )
				) {
				cerr << it->first << ": " << ( (*it->second)==T_IDENTIFIER && it->second->get_identifier_type() == symbolItem::T_CLASS_NAME?"CLASS_NAME":
					                           (*it->second)==T_IDENTIFIER && it->second->get_identifier_type() == symbolItem::T_ENUM_NAME?"ENUM_NAME":
						                       (*it->second)==T_IDENTIFIER && it->second->get_identifier_type() == symbolItem::T_ORIGINAL_NAMESPACE_NAME?"ORIGINAL_NAMESPACE_NAME":
						                       (*it->second)==T_IDENTIFIER && it->second->get_identifier_type() == symbolItem::T_TEMPLATE_NAME?"TEMPLATE_NAME":
						                       (*it->second)==T_IDENTIFIER && it->second->get_identifier_type() == symbolItem::T_NAMESPACE_ALIAS?"NAMESPACE_ALIAS":
						                       (*it->second)==T_IDENTIFIER && it->second->get_identifier_type() == symbolItem::T_TYPEDEF_NAME?"TYPEDEF_NAME":
						                       (*it->second)==T_IDENTIFIER && it->second->get_identifier_type() == symbolItem::T_TEMPLATE_PARAMETER?"TEMPLATE_PARAMETER":
						                       (*it->second)==T_IDENTIFIER && it->second->get_identifier_type() == symbolItem::T_TEMPLATE_VARIABLE?"TEMPLATE_VARIABLE":
											   (*it->second)==T_IDENTIFIER && it->second->get_identifier_type() == symbolItem::NONE
												   ? (    (!it->second->get_type_symbol()
												        ? ""
														: (   it->second->get_type_symbol()->to_str()
														    + adns2Str(it->second->get_type_symbol()->get_adorners())
														    + adns2Str(it->second->get_adorners())
														  ).c_str() )
												       + std::string(": IDENTIFIER")).c_str():
											   it->second->get_symbol_type()==symbolItem::keyword?"KEYWORD":
											   "UNKNOWN"
											 )
				      << ": " << ( (*it->second)==T_IDENTIFIER && it->second->get_identifier_type() == symbolItem::NONE ? symbolItem::strSymbolType[it->second->get_symbol_type()] : "" )
				      << ": " << (   (*it->second)==T_IDENTIFIER && it->second->get_identifier_type() == symbolItem::T_TYPEDEF_NAME 
				              ? (   it->second->get_type_symbol()
							      ? (   it->second->get_type_symbol()->to_str() 
								      + adns2Str(it->second->get_type_symbol()->get_adorners())
								      + adns2Str(it->second->get_adorners())
								    ).c_str()
								  :  "") 
							  : "" )
				      << (it->second->get_symbol_type()==symbolItem::keyword?"":
							( std::string(": (") + (*it->second).get_position().get_file().c_str() + ":"
				              + my_itoa((*it->second).get_position().get_line(),strLinNum) + "," 
							  + my_itoa((*it->second).get_position().get_column(),strColNum)
							  + ")" ).c_str())
				      << endl;

			if (it->second->get_references().size() > 0) {
				cerr << "     Referenced at: " << endl;
			    for (std::map<cnome_iterator, symbolItemPtr>::iterator itr = it->second->get_references().begin(); itr != it->second->get_references().end(); itr++) {
					cerr << "     " << (itr->second?itr->second->to_str():"") << endl;
			    }
			}
		}
	}
}

void readConfig(context_t& ctx) {
	ifstream file(cfgFile);

	if (!file)
		return;
	
	while(!file.eof())
	{
		char ch;
		file.get(ch);
		string cmd;
		getline(file, cmd);
		switch(ch) {
			case 'D':
				ctx.add_macro_definition(cmd, true);
				break;
			case 'I':
				ctx.add_include_path(cmd.c_str());
				break;
			case 'S':
				ctx.add_sysinclude_path(cmd.c_str());
				break;
		}
	}
}
}  // namespace cnome

#if defined(_MSC_VER) && (_MSC_VER >= 1400)
#pragma warning ( default : 4800 )
#pragma warning ( default : 4996 )
#pragma warning ( default : 4267 )
#pragma warning ( default : 4355 )
#endif

